package com.yao.yaoojcodesandbox.utils;

import cn.hutool.core.util.StrUtil;
import com.yao.yaoojcodesandbox.model.ExecuteMessage;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.StopWatch;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

/**
 * 进程工具类
 *
 */

public class ProcessUtils {

    /**
     * 执行代码并获取代码运行值信息
     * @param runProcess
     * @param opName
     * @return
     * @throws IOException
     */
    public static ExecuteMessage runProcessAndGetMessage(Process runProcess,String opName) throws IOException {
        ExecuteMessage executeMessage=new ExecuteMessage();
        try{
            StopWatch stopWatch=new StopWatch();
            stopWatch.start();
            int exitValue = runProcess.waitFor(); //直到这个程序完成，才会拿到错误码，根据错误码知道这个程序是正常退出还是异常退出
            //正常退出
            if(exitValue==0){
                System.out.println(opName + "成功");
                //获取编译过程中正常输出流
                BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(runProcess.getInputStream()));
                //getInputStream() 方法获取的是子进程的标准输出流（Standard Output Stream）如果编译命令成功执行，编译器的输出（如编译成功的提示信息）会通过这个流返回。
                //InputStreamReader将 InputStream 转换为字符流 Reader。这是因为 InputStream 处理的是字节数据，而 Reader 处理的是字符数据。
                //BufferedReader 是对 Reader 的封装，提供了缓冲功能，可以更高效地读取字符数据。它还支持按行读取数据的方法（如 readLine()），便于处理以行为单位的输出内容。
                List<String> outputStrList=new ArrayList<>();
//                StringBuilder compileOutputStringBuilder=new StringBuilder();

                String compileOutputLine;
                while((compileOutputLine = bufferedReader.readLine()) != null){ //逐行读取编译过程中出现的信息
                    outputStrList.add(compileOutputLine);
                    //compileOutputStringBuilder.append(compileOutputLine).append("\n");
                }
                //这里储存的信息就是编译的结果
                System.out.println("编译结果为！！！！"+StringUtils.join(outputStrList,"\n"));
                executeMessage.setMessage(StringUtils.join(outputStrList,"\n"));
            }else{
                //异常退出
                System.out.println(opName + "失败,错误码："+exitValue);
                //获取编译过程中正常输出流
                BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(runProcess.getInputStream()));
//                StringBuilder compileOutputStringBuilder=new StringBuilder();
                List<String> outputStrList=new ArrayList<>();
                String compileOutputLine;
                while((compileOutputLine = bufferedReader.readLine()) != null){ //逐行读取编译过程中出现的信息
                    outputStrList.add(compileOutputLine);
//                    compileOutputStringBuilder.append(compileOutputLine);
                }
                //这里储存的信息就是编译的结果
                System.out.println("编译结果为！！！！"+StringUtils.join(outputStrList,"\n"));
                executeMessage.setMessage(StringUtils.join(outputStrList,"\n"));

                //获取错误输出流 .getErrorStream
                BufferedReader errorbufferedReader=new BufferedReader(new InputStreamReader(runProcess.getErrorStream()));
                StringBuilder errorcompileOutputStringBuilder=new StringBuilder();
                List<String> erroroutputStrList=new ArrayList<>();
                //逐行读取
                String errorcompileOutputLine;
                while((errorcompileOutputLine = errorbufferedReader.readLine()) != null){ //逐行读取编译过程中出现的错误信息
                    erroroutputStrList.add(errorcompileOutputLine);
//                    errorcompileOutputStringBuilder.append(errorcompileOutputLine);
                }
                //这里储存的信息就是编译的结果
                System.out.println("编译结果为！！！！"+StringUtils.join(erroroutputStrList,"\n"));
                executeMessage.setMessage(StringUtils.join(erroroutputStrList,"\n"));
            }
            executeMessage.setExitValue(exitValue);
            stopWatch.stop();
            //设置运行时间
            executeMessage.setTime(stopWatch.getLastTaskTimeMillis());
            //获取运行时间
        }catch (Exception e){
            e.printStackTrace();
        }
        return executeMessage;
    }

    /**
     * 执行交互式进程并获取代码值信息
     * @param runProcess
     * @param opName
     * @return
     * @throws IOException
     */
    public static ExecuteMessage runInteractProcessAndGetMessage(Process runProcess,String opName,String args) throws IOException {
        ExecuteMessage executeMessage=new ExecuteMessage();
        try{
            //向控制台输入程序
            OutputStream outputStream = runProcess.getOutputStream();
            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream); //输出流写的对象
            String[] s=args.split(" ");
            String join= StrUtil.join("\n",s)+"\n";
            outputStreamWriter.write(join);
            outputStreamWriter.flush();//刷新缓冲区，将数据写入到输出流中 通俗易懂的说法就是你输入了1 2，然后按了回车

            //分批获取编译过程中正常输出流
            InputStream inputStream = runProcess.getInputStream();
            BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(inputStream));
            StringBuilder compileOutputStringBuilder=new StringBuilder();
            String compileOutputLine;
            while((compileOutputLine = bufferedReader.readLine()) != null){ //逐行读取编译过程中出现的信息
                compileOutputStringBuilder.append(compileOutputLine);
            }
            executeMessage.setMessage(compileOutputStringBuilder.toString());
            //记得资源的回收
            outputStream.close();
            outputStreamWriter.close();
            bufferedReader.close();
            inputStream.close();
        }catch (Exception e){
            e.printStackTrace();
        }
        return executeMessage;
    }
}
